home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / OCDOC.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  8KB  |  351 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.10  $
  6. //
  7. // Implementation of TOcDocument Class
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_OLEUTIL_H)
  11. # include <ocf/oleutil.h>
  12. #endif
  13. #if !defined(OCF_OCSTORAG_H)
  14. # include <ocf/ocstorag.h>
  15. #endif
  16. #if !defined(OCF_OCDOC_H)
  17. # include <ocf/ocdoc.h>
  18. #endif
  19. #if !defined(OCF_OCPART_H)
  20. # include <ocf/ocpart.h>
  21. #endif
  22. #if !defined(OCF_OCAPP_H)
  23. # include <ocf/ocapp.h>
  24. #endif
  25. #if !defined(OCF_OCREMVIE_H)
  26. # include <ocf/ocremvie.h>
  27. #endif
  28.  
  29. DIAG_DECLARE_GROUP(OcRefCount);
  30.  
  31. const char  DocStreamName[] = "OcDocument";
  32.  
  33. //
  34. //
  35. //
  36. TOcDocument::TOcDocument(TOcApp& app, const char far* fileName)
  37. :
  38.   OcApp(app),
  39.   Name(fileName),
  40.   PartCollection(),
  41.   LinkCollection()
  42. {
  43.   // Host support...
  44.   //
  45.   ActiveView = 0;
  46.   PartID     = 0;
  47.   Storage    = 0;
  48.  
  49.   bool createNew = ToBool(!fileName || !fileName[0]);
  50.   Storage = new TOcStorage(fileName, createNew);
  51.   TRACEX(OcRefCount, 1, "TOcDocument() @" << (void*)this);
  52. }
  53.  
  54. //
  55. //
  56. //
  57. TOcDocument::TOcDocument(TOcApp& app, const char far* fileName, IStorage far* storageI)
  58. :
  59.   OcApp(app),
  60.   Name(fileName),
  61.   PartCollection(),
  62.   LinkCollection()
  63. {
  64.   // Host support...
  65.   //
  66.   ActiveView = 0;
  67.   PartID     = 0;
  68.   Storage    = 0;
  69.   OrgStorage = 0;
  70.  
  71.   if (storageI)   // Storage already created by host application
  72.     Storage = new TOcStorage(storageI);
  73.   else
  74.     Storage = 0;  // No storage yet, wait until a SetStorage() is called
  75.   TRACEX(OcRefCount, 1, "TOcDocument() @" << (void*)this);
  76. }
  77.  
  78. //
  79. //
  80. //
  81. TOcDocument::~TOcDocument()
  82. {
  83.   delete Storage;
  84. }
  85.  
  86. //----------------------------------------------------------------------------
  87.  
  88. //
  89. // Set the storage for this document
  90. //
  91. void
  92. TOcDocument::SetStorage(IStorage* storage, bool remember)
  93. {
  94.   if (Storage && storage == Storage->GetIStorage())
  95.     return;
  96.  
  97.   if (remember) {
  98.     delete Storage;
  99.     OrgStorage = 0;
  100.   }
  101.   else
  102.     OrgStorage = Storage;
  103.  
  104.   if (storage)
  105.     Storage = new TOcStorage(storage);
  106.   else
  107.     Storage = 0;
  108. }
  109.  
  110. //
  111. // Set the storage for this document
  112. //
  113. void
  114. TOcDocument::SetStorage(const char far* path)
  115. {
  116.   delete Storage;
  117.   Storage = new TOcStorage(path, false);
  118.   SetName(path);    // new Storage now has path as a name
  119. }
  120.  
  121. //
  122. // Restore the original root IStorage before the save operation
  123. //
  124. bool
  125. TOcDocument::RestoreStorage()
  126. {
  127.   if (OrgStorage) {
  128.     delete Storage;
  129.  
  130.     Storage    = OrgStorage;
  131.     OrgStorage = 0;
  132.   }
  133.  
  134.   return true;
  135. }
  136.  
  137. //
  138. // Perform saveas operation
  139. //
  140. bool
  141. TOcDocument::SaveToFile(const char far* newName)
  142. {
  143.   PRECONDITION(newName);
  144.  
  145.   TOcStorage newStorage(newName, true);
  146.   Name = newName;
  147.   return SaveParts(newStorage.GetIStorage(), false);
  148. }
  149.  
  150. //
  151. // Save the embedded parts to the provided storage. 'remember' flag is not
  152. // really used here, as our save/restore is done outside here.
  153. //
  154. bool
  155. TOcDocument::SaveParts(IStorage* storage, bool sameAsLoaded, bool remember)
  156. {
  157.   if (!Storage)
  158.     return true;
  159.  
  160.   TOcStorage* oldStorage = 0;
  161.  
  162.   // If the storage passed is not the same as the one we loaded, wrap the new
  163.   // one & use it in here.
  164.   //
  165.   if (!sameAsLoaded) {
  166.     CHECK(storage);
  167.  
  168.     // If we are switching storages, make sure parts all all pulled in now
  169.     //
  170.     for (TOcPartCollectionIter i(PartCollection); i; i++) {
  171.       TOcPart& part = *i.Current();
  172.       part.FinishLoading();
  173.     }
  174.     oldStorage = Storage;
  175.     Storage = new TOcStorage(storage);
  176.   }
  177.  
  178.   // Create a stream for part information
  179.   //
  180.   STATSTG statstg;
  181.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  182.     return false;
  183.  
  184.   TOcStream  stream(*Storage, ::DocStreamName, true, statstg.grfMode);
  185.  
  186.   // Write TOcDocument data into stream
  187.   //
  188.   ulong count;
  189.   bool  ok;
  190.   ulong value = PartCollection.Count();
  191.   ok = ToBool(HRSucceeded(stream.Write(&PartID, sizeof PartID, &count)) &&
  192.               HRSucceeded(stream.Write(&value, sizeof value, &count)));
  193.  
  194.   if (ok) {
  195.     for (TOcPartCollectionIter i(PartCollection); i; i++) {
  196.       TOcPart& part = *i.Current();
  197.       int16 len = int16(part.GetName().Length());
  198.  
  199.       // Write the part name string, pascal style [len]+chars, no 0
  200.       //
  201.       ok = ToBool(HRSucceeded(stream.Write(&len, sizeof len, &count)) &&
  202.                   HRSucceeded(stream.Write((char far*)part.GetName(), len, &count)) &&
  203.                   part.Save(sameAsLoaded, remember));
  204.  
  205.       if (!ok)
  206.         break;
  207.     }
  208.   }
  209.  
  210.   // Deal with the alloc'd storage if there was one. Either put things back on
  211.   // failure, or keep the new storage around for a while
  212.   //
  213.   if (!sameAsLoaded) {
  214.     if (!ok) {
  215.       delete Storage;
  216.       Storage = oldStorage;
  217.     }
  218.     else
  219.       delete oldStorage;
  220.   }
  221.  
  222.   return ok;
  223. }
  224.  
  225. //
  226. // Loads the parts from the current storage into the PartCollection. Return
  227. // false if a serious error occurs. Having no part stream at all is OK.
  228. //
  229. bool
  230. TOcDocument::LoadParts()
  231. {
  232.   if (!Storage)
  233.     return true;
  234.  
  235.  
  236.   // Open a stream with part information
  237.   //
  238.   STATSTG statstg;
  239.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  240.     return false;
  241.  
  242.   try {
  243.     TOcStream  stream(*Storage, ::DocStreamName, false, statstg.grfMode);
  244.  
  245.     // Read TOcDocument data from stream. Return false if any of the data
  246.     // is missing--something must have been corrupted.
  247.     //
  248.     if (!HRSucceeded(stream.Read(&PartID, sizeof PartID)))
  249.       return false;
  250.  
  251.     ulong value;
  252.     if (!HRSucceeded(stream.Read(&value, sizeof value)))
  253.       return false;
  254.  
  255.     // Clear the part collection
  256.     //
  257.     PartCollection.Clear();
  258.  
  259.     // Rebuild the part collection
  260.     //
  261.     for (int i = (int)value; i; i--) {
  262.       char name[33];
  263.       int16 len;
  264.  
  265.       // Read the part name string, pascal style [len]+chars, no 0
  266.       //
  267.       if (!HRSucceeded(stream.Read(&len, sizeof(len))))
  268.         return false;
  269.  
  270.       if (len >= sizeof(name)) {
  271.         // NOTE: Should *never* happen!
  272.         //
  273.         return false;
  274.       }
  275.  
  276.       if (!HRSucceeded(stream.Read(name, len)))
  277.         return false;
  278.       name[len] = 0;  // 0 was not written
  279.  
  280.       new TOcPart(*this, name);
  281.     }
  282.   }
  283.   catch (TXObjComp&) {
  284.     // There is no part related info stream. Thats OK, we then have a document
  285.     // with no parts
  286.   }
  287.   return true;
  288. }
  289.  
  290. //
  291. //
  292. //
  293. void
  294. TOcDocument::RenameParts(IBRootLinkable far* bLDocumentI)
  295. {
  296.   if (Name.is_null())
  297.     return; // Temporary file does not have moniker
  298.  
  299.   for (TOcPartCollectionIter i(PartCollection); i; i++) {
  300.     TOcPart& part = *i.Current();
  301.  
  302.     IBLinkable far* linkI;
  303.     if (HRSucceeded(part.QueryInterface(IID_IBLinkable, &(LPVOID)linkI))) {
  304.       linkI->OnRename(bLDocumentI, part.GetName());
  305.       linkI->Release();
  306.     }
  307.   }
  308. }
  309.  
  310. //
  311. //
  312. //
  313. void
  314. TOcDocument::Close()
  315. {
  316.   for (TOcPartCollectionIter i(PartCollection); i; i++) {
  317.     TOcPart& part = *i.Current();
  318.     part.Close();
  319.   }
  320.  
  321.   for (TOcLinkCollectionIter j(LinkCollection); j; j++) {
  322.     TOcLinkView& link = *j.Current();
  323.     link.Disconnect();
  324.   }
  325.  
  326.   LinkCollection.Clear();  // Remove the link views now
  327. }
  328.  
  329. //
  330. //
  331. //
  332. void
  333. TOcDocument::SetActiveView(TOcView* view)
  334. {
  335.   ActiveView = view;
  336. }
  337.  
  338. //
  339. // Notify container that doc pathname has changed
  340. //
  341. void
  342. TOcDocument::SetName(const string& newName)
  343. {
  344.   Name = newName;
  345.  
  346.   // Create a moniker for this document
  347.   //
  348.   if (!Name.is_null() && ActiveView)
  349.     ActiveView->Rename();
  350. }
  351.